<?php


namespace App\Web\Model;


use EchoPHP\Facades\Db;
use EchoPHP\Facades\Redis;

class Message {

    /**
     * type = 01 系统通知
     * type = 02 待我处理
     */
    const MSG_TYPE_NOTICE = '01';
    const MSG_TYPE_HANDLE = '02';

    /**
     * 消息期限，超过这个时间的消息全部当做已读处理
     * @var string
     */
    private $messageDeadLine = '-14 Days';

    /**
     * 获取消息列表
     * @param $userId 消息接受者ID
     * @param int $lastId 最后一条消息id，用于获取比这条消息更小的数据，提升查询效率
     * @param string $type 消息类型 系统通知或待我处理
     * @param string $readStatus unread 只获取未读消息 all 获取全部消息
     * @return array
     */
    public function getMessageList($userId, $lastId = 0, $type = self::MSG_TYPE_HANDLE, $readStatus = 'all') {
        $sql = 'SELECT id,content,userid,type,module,createdate,readstatus FROM Message WHERE userid = ? AND status=? AND type = ?';
        $var = [$userId, '01', ($type == self::MSG_TYPE_NOTICE ? '01' : '02')];
        if ($readStatus == 'unread') {
            $sql .= ' AND readstatus=?';
            $var[] = 0;
        }
        if ($lastId > 0) {
            $sql .= ' AND id<?';
            $var[] = $lastId;
        }
        $sql .= ' ORDER BY id DESC';

        $messageList = Db::select($sql, $var, 0, 20);
        return $messageList;
    }

    /**
     * 批量更新未读消息
     * @param $userId
     * @param $messageIds
     * @return bool
     */
    public function handleReadStatus($userId, array $messageIds) {
        if (empty($messageIds)) {
            return true;
        }
        $sql = 'SELECT id,type FROM Message WHERE id IN(' . mergeArrSql($messageIds) . ') AND userid=? AND readstatus=?';
        $var = array_merge($messageIds, [$userId, 0]);
        $messageList = Db::select($sql, $var);
        if (empty($messageList)) {
            return true;
        }
        $messageIds = [];
        $type = $messageList[0]['type'];
        foreach ($messageList as $item) {
            $messageIds[] = intval($item['id']);
            if ($type != $item['type']) {
                //消息类型不一致，不更新
                return false;
            }
        }

        $sql = 'UPDATE Message SET readstatus=?,updatedate=Now() WHERE id IN(' . mergeArrSql($messageIds) . ') AND readstatus=?';
        $var = array_merge(['1',], $messageIds, ['0']);

        $result = Db::connect()->update($sql, $var);
        $this->dealUnreadCountInCache($userId, $type, $result);
        return true;
    }

    /**
     * 清空所有未读消息状态,未读消息最多保持两个月，另外有脚本专门清理超过两个月的未读消息
     * @param $userId
     * @param $type
     * @return bool
     */
    public function handleAllReadStatus($userId, $type) {
        $typeValue = $type == self::MSG_TYPE_NOTICE ? '01' : '02';
        $sql = 'UPDATE Message SET readstatus=?,updatedate=Now() WHERE userid=? AND createdate>= ? AND type = ? AND readstatus=?';
        $var = [1, $userId, date('Y-m-d 00:00:00', strtotime($this->messageDeadLine)), $typeValue, 0];
        $result = Db::update($sql, $var);
        $this->dealUnreadCountInCache($userId, $typeValue, $result);

        return true;
    }

    /**
     * 处理存放在redis中的未读消息总数
     * @param $userId
     * @param $msgType
     * @param $msgCount
     * @return bool
     */
    private function dealUnreadCountInCache($userId, $msgType, $msgCount) {
        if ($msgCount <= 0) {
            return true;
        }
        $storeKey = 'messagenotice:' . $userId . ':' . $msgType;
        $redisClient = Redis::connect('noticecount');
        $unreadCount = $redisClient->get($storeKey);
        if ($unreadCount === false) {
            return true;
        }
        if ($unreadCount >= $msgCount) {
            $redisClient->decrBy($storeKey, $msgCount);
        } else {
            //自减之后变为负数了则直接删除
            $redisClient->del($storeKey);
        }
    }

    /**
     * 批量处理消息未读状态，用于处理两个月前的消息
     * @param int $userId
     * @return bool
     */
    public function handleAllReadStatusBefore($userId = 0) {
        $deadLineStart = date('Y-m-d 00:00:00', strtotime($this->messageDeadLine . ' -2 day'));
        $deadLineEnd = date('Y-m-d 23:59:59', strtotime($this->messageDeadLine . ' -1 day'));
        $sql = 'UPDATE Message SET readstatus=?,updatedate=Now() WHERE ';
        $var = [1];
        if ($userId > 0) {
            $sql .= ' userid=? AND ';
            $var[] = $userId;
        }
        $sql .= 'createdate>= ? AND createdate <= ? AND readstatus=?';
        $var = array_merge($var, [$deadLineStart, $deadLineEnd, 0]);
        $result = Db::update($sql, $var);
        return true;
    }
}